use std::collections::HashMap;
use std::fs;
use std::io::Write;
use std::path::Path;
use std::time::SystemTime;
use serde::{Serialize, Deserialize};
use tera::Tera;


#[derive(Serialize, Deserialize, Debug)]
struct Summary {
    success: bool,
    stat: Stat,
    time: TestCaseTime,
    platform: Platform,
    details: Vec<TestCaseSummary>,
    root_dir: String,
}

#[derive(Serialize, Deserialize,Debug)]
struct Stat {
    test_cases: TestCaseStat,
    test_steps: TestStepStat,
}

#[derive(Serialize, Deserialize,Debug)]
struct TestCaseStat {
    total: i32,
    success: i32,
    fail: i32,
}

#[derive(Serialize, Deserialize,Debug)]
struct TestStepStat {
    total: i32,
    successes: i32,
    failures: i32,
}

#[derive(Serialize, Deserialize,Debug)]
struct TestCaseTime {
    start_at: SystemTime,
    duration: f64,
}

#[derive(Serialize, Deserialize,Debug)]
struct Platform {
    httprunner_version: String,
    go_version: String,
    platform: String,
}

#[derive(Serialize, Deserialize,Debug)]
pub struct TestCaseSummary {
    name: String,
    success: bool,
    case_id: Option<String>,
    stat: TestStepStat,
    time: TestCaseTime,
    in_out: TestCaseInOut,
    logs: Option<Vec<String>>,
    records: Vec<StepResult>,
    root_dir: String,
}

impl TestCaseSummary {
   pub fn new()->TestCaseSummary{
        return TestCaseSummary{
            name: "".to_string(),
            success: false,
            case_id: None,
            stat: TestStepStat {
                total: 0,
                successes: 0,
                failures: 0,
            },
            time: TestCaseTime { start_at: SystemTime::now(), duration: 0.0 },
            in_out: TestCaseInOut { config_vars: None, export_vars: None },
            logs: None,
            records: vec![],
            root_dir: "".to_string(),
        }
    }
}

#[derive(Serialize, Deserialize,Debug)]
struct TestCaseInOut {
    config_vars: Option<HashMap<String, serde_json::Value>>,
    export_vars: Option<HashMap<String, serde_json::Value>>,
}

#[derive(Serialize, Deserialize,Debug)]
struct StepResult {
    // Define your StepResult struct fields here
}

impl Summary {
    fn gen_html_report(&self) -> std::io::Result<()> {
        let reports_dir = Path::new(&self.root_dir).join("results");
        fs::create_dir_all(&reports_dir)?;

        let report_path = reports_dir.join("report.html");
        let file = fs::File::create(&report_path)?;

        let mut writer = std::io::BufWriter::new(&file);
         let mut tera = Tera::new("templates/**/*").unwrap();
        let rendered = tera.render("template", &tera::Context::new()).unwrap();
        writer.write_all(rendered.as_bytes())?;

        Ok(())
    }

    fn gen_summary(&self) -> std::io::Result<()> {
        let reports_dir = Path::new(&self.root_dir).join("results");
        fs::create_dir_all(&reports_dir)?;

        let summary_path = reports_dir.join("summary.json");
        let summary_json = serde_json::to_string_pretty(&self)?;
        fs::write(&summary_path, summary_json)?;

        Ok(())
    }
}